﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Chrome4Net.NativeMessaging;
using System.Threading;
using log4net;
using QlrrPrintService.Common;
using System.ServiceProcess;
using PluginBase;
using PluginBase.Sockets;

namespace QlrrPrintService.NativeMessage
{
    public class Host
    {

        #region fileds

        private static ILog _log = LogManager.GetLogger(typeof(Host));

        private ManualResetEvent _stop;
        private Port _port;

        AsyncSocketConnect<PluginResponseMessage> _socket = null;

        private static string _serviceName = "QlrrPrintService";

        

        #endregion

        #region constructor
        
        
        /// <summary>
        /// Creates a new instance of native messaging host.
        /// </summary>
        public Host()
        {
            _port = new Port();
            _stop = new ManualResetEvent(false);
            _socket = AsyncSocketConnect<PluginResponseMessage>.CreateClientSocket();
            _socket.IRecieveArgs = new PluginResponseMessageReceiveArgs();
            _socket.OnReceivedMessage += new HandleMessageHandler<PluginResponseMessage>(OnReceivedMessage);
            _socket.OnError += new ExceptionHandler(OnSocketError);
        }

        

      

        

        #endregion

        #region public methods

        
        /// <summary>
        /// Starts native message processing.
        /// </summary>
        public void Run()
        {
            if (!ServiceIsExisted(_serviceName))
            {
                PluginResponseMessage message = new PluginResponseMessage();
                message.PluginMessageType = PluginMessageType.ErrorInfo;
                message.MessageBody = Newtonsoft.Json.JsonConvert.SerializeObject(new ErrorInfo() { Msg="请先安装其乐融融相关Windows服务",ErrInfoType=ErrInfoType.NotInstallService});
                WriteMessage(message);
                //_port.Write(Newtonsoft.Json.JsonConvert.SerializeObject(message));
            }
            else
            {
                if (StartService(_serviceName))
                {
                    _socket.ConnectToServer("127.0.0.1", 6000);

                    _stop.Reset();
                    while (!_stop.WaitOne(0))
                    {
                        try
                        {
                            string message = _port.Read();
                            if (!string.IsNullOrEmpty(message))
                            {
                                _socket.AsyncSend(System.Text.ASCIIEncoding.UTF8.GetBytes(message + "**"));
                            }

                        }
                        catch (EndOfInputStreamException)
                        {
                            _log.Debug("end of input stream");
                            _stop.Set();
                        }
                        catch (Exception ex)
                        {
                            _log.Error("message processing caused an exception", ex);
                            _stop.Set();
                        }
                    }

                    _log.Info("host stopped*********************");
                }
                else
                {
                    PluginResponseMessage message = new PluginResponseMessage();
                    message.PluginMessageType = PluginMessageType.ErrorInfo;
                    message.MessageBody = Newtonsoft.Json.JsonConvert.SerializeObject(new ErrorInfo() { Msg = "无法启动其乐融融相关Windows服务",ErrInfoType=ErrInfoType.CanNotInstallService });
                    WriteMessage(message);
                    //_port.Write(Newtonsoft.Json.JsonConvert.SerializeObject(message));
                }
            }


            
        }

        /// <summary>
        /// Stops native message processing.
        /// </summary>
        public void Stop()
        {
            _log.Info("开始退出_______________");
            try
            {
                
                _socket.Close();
            }
            catch(Exception ex)
            { _log.Error(ex.Message); }
            
            _stop.Set();
        }

        #endregion

        #region protected

        protected virtual void OnReceivedMessage(AsyncMessageHandleArgs<PluginResponseMessage> args)
        {
            try
            {
                if (args != null && args.Msg != null)
                {
                    _log.Info(string.Format("收到一个消息{0}", Newtonsoft.Json.JsonConvert.SerializeObject(args.Msg)));
                    WriteMessage(args.Msg);
                    //_port.Write(Newtonsoft.Json.JsonConvert.SerializeObject(args.Msg));
                    
                }
                
            }
            catch(Exception ex)
            {
                _log.Error(ex.Message);
            }
        }



        protected virtual void OnSocketError(object sender, Exception e)
        {
            try
            {
                PluginResponseMessage message = new PluginResponseMessage();
                message.PluginMessageType = PluginMessageType.ErrorInfo;
                message.MessageBody = Newtonsoft.Json.JsonConvert.SerializeObject(new ErrorInfo() 
                { Msg = "未知的错误"+e.Message, ErrInfoType = ErrInfoType.UnKnow });
                WriteMessage(message);
            }
            catch
            { }
            throw new NotImplementedException();
        }

        #endregion

        #region private methods

        private bool ServiceIsExisted(string serviceName)
        {

            ServiceController[] services = ServiceController.GetServices();

            foreach (ServiceController s in services)
            {

                if (s.ServiceName == serviceName)
                {

                    return true;

                }

            }

            return false;

        }

        private bool StartService(string serviceName)
        {

            bool flag = true;

            if (ServiceIsExisted(serviceName))
            {

                System.ServiceProcess.ServiceController service = new System.ServiceProcess.ServiceController(serviceName);

                if (service.Status != System.ServiceProcess.ServiceControllerStatus.Running && service.Status != System.ServiceProcess.ServiceControllerStatus.StartPending)
                {

                    service.Start();

                    for (int i = 0; i < 60; i++)
                    {
                        service.Refresh();

                        System.Threading.Thread.Sleep(1000);

                        if (service.Status == System.ServiceProcess.ServiceControllerStatus.Running)
                        {

                            break;

                        }

                        if (i == 58)
                        {

                            flag = false;

                        }

                    }

                }

            }

            return flag;

        }

        private void WriteMessage(Object obj)
        {
            try
            {
                _port.Write(Newtonsoft.Json.JsonConvert.SerializeObject(obj));
            }
            catch
            {
 
            }
            
        }

        #endregion
    }
}
